package broker

import (
	"context"
	"encoding/json"
	"fmt"
	"manager/bll"
	"manager/lib/trace_log"
	"manager/model"
	"manager/model/entity"
	"manager/model/po"
	"manager/store/postgres"
	"manager/store/redis"
	"manager/utils"
	"proto/dto"
	"time"
)

const (
	// MaxRecodeLocationCount 最大坐标点数
	MaxRecodeLocationCount = 300
)

var Location = &location{}

type location struct {
}

// FilterLocation 过滤坐标点
func (l *location) FilterLocation(trackList []po.GpsLocation) (list []po.GpsLocation) {
	if len(trackList) > MaxRecodeLocationCount {
		skipValue := len(trackList) / MaxRecodeLocationCount
		skipCount := 0
		for i := 0; i < len(trackList); i++ {
			if i == 0 {
				list = append(list, trackList[i])
			} else {
				if i == len(trackList)-1 {
					list = append(list, trackList[i])
					break
				}
				if skipValue-1 > skipCount {
					skipCount++
					continue
				} else {
					list = append(list, trackList[i])
					skipCount = 0
				}
			}
		}
	} else {
		list = append(list, trackList...)
	}
	return
}

// PopLocation 坐标
func (l *location) PopLocation(bikeId, userId int64) (trackId int64, list []*dto.Location, err error) {
	// 数据落库
	results := redis.KV.ListRange(context.Background(), fmt.Sprintf("%v:%v", DeviceLocationKey, bikeId), 0, -1)
	if len(results) == 0 {
		return
	}

	bikeInfo, _ := bll.CacheBike.GetBikeInfoById(bikeId)

	var id int64

	// 从数据库中查询
	_, routeList, _ := postgres.RouteList.List(&model.RouteListListRequest{
		Index:   1,
		Size:    1,
		EbikeId: bikeId,
	}, true)

	if len(routeList) == 0 {
		// 创建骑行记录
		id, err = postgres.RouteList.Create(&entity.RouteList{
			EbikeId: bikeId,
			UserId:  userId,
		})
		if err != nil {
			trace_log.DebugLogger(bikeInfo.SNCode, "PopLocation RouteList Create err:", err)
			return
		}
	} else {
		id = routeList[0].Id
		if routeList[0].IsFinish == 1 {
			err = fmt.Errorf("骑行记录已结束")
			return
		}
	}

	for i := 0; i < len(results); i++ {
		lo := dto.Location{}
		err = json.Unmarshal([]byte(results[i]), &lo)
		if err != nil {
			trace_log.DebugLogger(bikeInfo.SNCode, "PopLocation Unmarshal err:", err, " data:", results[i])
			continue
		}

		list = append(list, &lo)
	}

	trackId = id
	return
}

// PushLocation 落库坐标
func (l *location) PushLocation(bikeId int64, data *dto.Location) (err error) {
	if data.Lat == 0 && data.Lng == 0 {
		return nil
	}
	data.Time = int32(time.Now().Unix())
	// 记录位置
	key := fmt.Sprintf("%v:%v", DeviceLocationKey, bikeId)
	if bSuccess := redis.KV.AddList(context.Background(), key, utils.ToJsonString(data)); !bSuccess {
		bikeInfo, _ := bll.CacheBike.GetBikeInfoById(bikeId)
		if bikeInfo != nil {
			trace_log.DebugLogger(bikeInfo.SNCode, "consumer PushLocation LocationReport failed")
		}

		return nil
	}

	// 设置过期时间
	redis.KV.Expire(context.Background(), redis.CacheList, key, time.Minute*10)
	return
}
